using System;
using System.Collections.Generic;

namespace OffsetPath
{
    public class PresuntoSkeletroClassAe
    {
        private List<ClassAr> a = new List<ClassAr>();
        private bool flagNeedSorting; // 
        /*
         * allora c contiene skeletro dopo elaborazione
         * 
         * c.d contiene punto comune di 2 segmenti dopo elaborazione
         * ho provato a cambiare ma senza risultati..
         * c.g contiene le linee per disegnare l'offset, non cambia nulla..
         */
        private List<ClassAa_OssaSkeletro> contenitoreOssa = new List<ClassAa_OssaSkeletro>();
        private static ClassAa_OssaSkeletro.SubClassA d = new ClassAa_OssaSkeletro.SubClassA();
        private LinkedList<ClassAa_OssaSkeletro> linkedList_e = new LinkedList<ClassAa_OssaSkeletro>(); // qui albero skeletro
        private bool f;
        private ClassAb g = new ClassAb(double.MinValue, double.MaxValue, double.MaxValue, double.MinValue);
        private double h = double.MinValue;
        private List<ClassF> i = new List<ClassF>();

        public double MethodA()
        {
            if (this.contenitoreOssa.Count > 0)
            {
                return double.MinValue;
            }
            return this.h;
        }

        private void MethodA(ClassAa_OssaSkeletro A_0)
        {
            if (A_0.MethodAa() && (A_0.MethodA(d) == null))
            {
                LinkedListNode<ClassAa_OssaSkeletro> node = this.linkedList_e.AddLast(A_0);
                A_0.MethodA(d, node);
            }
        }

        public void MethodA(ClassAb A_0)
        {
            this.g.g(A_0);
        }

        public void MethodA(ClassAr A_0)
        {
            this.a.Add(A_0);
            A_0.MethodA(this);
        }

        public void MethodA(ClassF A_0)
        {
            this.i.Add(A_0);
        }

        public void MethodA(double A_0)
        {
            this.h = A_0;
            if (this.linkedList_e.Count != 0)
            {
                foreach (ClassAa_OssaSkeletro aa in this.linkedList_e)
                {
                    if (aa.MethodAa())
                    {
                        if (aa.MethodA(A_0))
                        {
                            this.flagNeedSorting = true;
                        }
                        aa.MethodA(d, null);
                    }
                }
                this.linkedList_e.Clear();
                this.RiordinaOssa();
            }
        }

        public ClassF MethodA(int A_0)
        {
            return this.i[A_0];
        }

        /// <summary>
        /// Riordino ossa , centra la diagonale..
        /// </summary>
        /// <param name="A_0"></param>
        /// <param name="A_1"></param>
        /// <returns></returns>
        private static int RiordinaOssa(ClassAa_OssaSkeletro A_0, ClassAa_OssaSkeletro A_1)
        {
            if (A_0 != A_1)
            {
                if (!A_0.MethodI() && !A_1.MethodI())
                {
                    return 0;
                }
                if (!A_0.MethodI() && A_1.MethodI())
                {
                    return -1;
                }
                if (A_0.MethodI() && !A_1.MethodI())
                {
                    return 1;
                }
                bool flag = double.IsNaN(A_0.MethodH()) || double.IsInfinity(A_0.MethodH());
                bool flag2 = double.IsNaN(A_1.MethodH()) || double.IsInfinity(A_1.MethodH());
                if (flag && flag2)
                {
                    return 0;
                }
                if (flag)
                {
                    return -1;
                }
                if (flag2)
                {
                    return 1;
                }
                if (Math.Abs((double) (A_0.MethodH() - A_1.MethodH())) > ClassAtAs.MethodB())
                {
                    if (A_0.MethodH() > A_1.MethodH())
                    {
                        return -1;
                    }
                    if (A_0.MethodH() < A_1.MethodH())
                    {
                        return 1;
                    }
                }
                if (A_0.MethodG() && !A_1.MethodG())
                {
                    return 1;
                }
                if (!A_0.MethodG() && A_1.MethodG())
                {
                    return -1;
                }
                if (A_0.MethodT() && !A_1.MethodT())
                {
                    return 1;
                }
                if (!A_0.MethodT() && A_1.MethodT())
                {
                    return -1;
                }
                if (A_0.MethodD() && !A_1.MethodD())
                {
                    return -1;
                }
                if (!A_0.MethodD() && A_1.MethodD())
                {
                    return 1;
                }
            }
            return 0;
        }

        public void MethodA(ClassAa_OssaSkeletro A_0, double A_1)
        {
            foreach (ClassAa_OssaSkeletro aa in A_0.methodY())
            {
                this.MethodA(aa.MethodW(), A_1, true);
            }
        }

        private void MethodA(SkeletroBaseLineaClasseI A_0, double A_1, bool A_2 = true)
        {
            if (A_2)
            {
                foreach (ClassAa_OssaSkeletro aa in A_0.MethodD())
                {
                    this.MethodA(aa);
                }
            }
            IEnumerable<ClassL> enumerable = A_0.o();
            if (enumerable != null)
            {
                foreach (ClassL l in enumerable)
                {
                    ClassAa_OssaSkeletro aa2 = l.MethodE();
                    if (aa2.MethodAa() && aa2.MethodA(l, A_1))
                    {
                        this.MethodA(aa2);
                    }
                }
            }
        }

        public void MethodA(ClassAa_OssaSkeletro A_0, ClassAa_OssaSkeletro A_1, ClassAa_OssaSkeletro A_2, double A_3)
        {
            this.MethodA(A_0.MethodW(), A_3, true);
            this.MethodA(A_1.MethodC(), A_3, true);
            this.MethodA(A_1.MethodW(), A_3, true);
            this.MethodA(A_2.MethodC(), A_3, true);
            this.MethodA(A_2.MethodW(), A_3, true);
            this.MethodA(A_1.MethodN());
            this.MethodA(A_1.Method());
            this.MethodA(A_2.MethodN());
            this.MethodA(A_2.Method());
        }

        public void MethodA(ClassAa_OssaSkeletro A_0, ClassAa_OssaSkeletro A_1, ClassAa_OssaSkeletro A_2, ClassAr A_3, ClassAr A_4, double A_5)
        {
            this.MethodA(A_0.MethodW(), A_5, true);
            this.MethodA(A_1.MethodC(), A_5, true);
            this.MethodA(A_1.MethodW(), A_5, true);
            this.MethodA(A_2.MethodC(), A_5, true);
            this.MethodA(A_2.MethodW(), A_5, true);
            this.MethodA(A_1.MethodN());
            this.MethodA(A_1.Method());
            this.MethodA(A_2.MethodN());
            this.MethodA(A_2.Method());
        }

        public int MethodB()
        {
            return this.contenitoreOssa.Count;
        }

        public void MethodB(ClassAa_OssaSkeletro A_0)
        {
            this.contenitoreOssa.Add(A_0);
            this.flagNeedSorting = true;
        }

        public void MethodB(ClassAr A_0)
        {
            if (A_0 == null)
            {
                throw new ArgumentNullException();
            }
            if (!this.a.Remove(A_0))
            {
                throw new InvalidOperationException();
            }
            A_0.MethodA((PresuntoSkeletroClassAe) null);
        }

        public ClassAa_OssaSkeletro MethodB(int A_0)
        {
            return this.contenitoreOssa[A_0];
        }

        public void MethodB(ClassAa_OssaSkeletro A_0, double A_1)
        {
            this.MethodA(A_0.MethodW(), A_1, false);
        }

        public void MethodB(ClassAa_OssaSkeletro A_0, ClassAa_OssaSkeletro A_1, ClassAa_OssaSkeletro A_2, double A_3)
        {
            this.MethodA(A_1.MethodW(), A_3, true);
            this.MethodA(A_2.MethodW(), A_3, true);
            this.MethodA(A_0.MethodC(), A_3, true);
            this.MethodA(A_0.MethodW(), A_3, true);
            this.MethodA(A_0.MethodN().MethodC(), A_3, true);
            this.MethodA(A_0.Method().MethodW(), A_3, true);
            this.MethodA(A_0.MethodN());
            this.MethodA(A_0.Method());
        }

        public void MethodC()
        {
            foreach (ClassAr ar in this.a)
            {
                if (ar.MethodB())
                {
                    this.f = true;
                    return;
                }
            }
            this.f = false;
        }

        public int MethodD()
        {
            return this.i.Count;
        }

        public ClassAb MethodE()
        {
            return this.g;
        }

        public IEnumerable<ClassAr> MethodF()
        {
            return this.a;
        }

        /// <summary>
        /// Crea Skeletro ---
        /// Richiamato da tutti i metodi..
        /// 
        /// Devo capire quale membro di aa viene usato per calcolare il punto centrale
        /// </summary>
        public void MethodG()
        {
            foreach (ClassAr ar in this.a)
            {
                foreach (ClassAa_OssaSkeletro aa in ar.MethodC())
                {
                    // Qui crea punto definitivo skeletro
                    ClassAa_OssaSkeletro item = aa.MethodK();
                    item.GetLineaImp().a.AngleStart = aa.GetLineaImp().a.AngleStart;
                    if (item != null)
                    {
                        this.contenitoreOssa.Add(item);
                    }
                }
            }
            this.flagNeedSorting = true;
            
            this.RiordinaOssa();
        }

        public ClassAa_OssaSkeletro MethodH()
        {
            if (this.contenitoreOssa.Count == 0)
            {
                return null;
            }
            ClassAa_OssaSkeletro classAa = this.contenitoreOssa[this.contenitoreOssa.Count - 1];
            this.contenitoreOssa.RemoveAt(this.contenitoreOssa.Count - 1);
            return classAa;
        }

        public void MethodI()
        {
            this.a.Clear();
            this.flagNeedSorting = false;
            this.contenitoreOssa.Clear();
            foreach (ClassAa_OssaSkeletro aa in this.linkedList_e)
            {
                aa.MethodA(d, null);
            }
            this.linkedList_e.Clear();
            this.f = false;
            this.i.Clear();
        }

        public bool MethodJ()
        {
            return this.f;
        }

        /// <summary>
        /// Riordina ossa, penso venga chiamato alla fine dell'elaborazione
        /// </summary>
        public void RiordinaOssa()
        {
            if (this.flagNeedSorting)
            {
                this.contenitoreOssa.Sort(new Comparison<ClassAa_OssaSkeletro>(PresuntoSkeletroClassAe.RiordinaOssa));
                this.flagNeedSorting = false;
            }
        }
    }
}

